/******************************************************************************
 * Copyright 2022 The Untouch Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#pragma once
#include <guik/camera_control.hpp>
#include <guik/gl_canvas.hpp>
#include <guik/imgui_application.hpp>
#include <guik/progress_modal.hpp>

#include "modules/calibration/lidar_imu_calibrator/include/odometry_frame_set.h"
#include "modules/calibration/lidar_imu_calibrator/include/version_modal.h"
#include "modules/calibration/lidar_imu_calibrator/include/self_lidar_imu_calibrator.h"

namespace lidar_imu_calibrator {

class LidarImuCalibratorApplication : public guik::Application {
 public:
  struct KeyFrameParameter {
    float key_frame_delta_x_;
    float key_frame_delta_angle_;
    float x_;
    float y_;
    float z_;
    float roll_;
    float pitch_;
    float yaw_;
    float delay_time_;
    bool delta_updated_;
    std::string title_;
  };
  LidarImuCalibratorApplication();
  ~LidarImuCalibratorApplication();
  bool init(const char* window_name, const Eigen::Vector2i& size,
            const char* glsl_version = "#version 330") override;
  virtual void draw_ui() override;
  virtual void draw_gl() override;
  virtual void framebuffer_size_callback(const Eigen::Vector2i& size) override;

 private:
  void ResetKeyFrameParameter(
      const Eigen::Isometry3d& extrinsic,
      std::shared_ptr<KeyFrameParameter>& key_frame_parameter,
      const std::string& title);
  void DrawKeyFrameSettingDialog(
      std::shared_ptr<KeyFrameParameter>& key_frame_parameter,
      std::shared_ptr<OdometryFrameSet>& odometry_frame_set);
  void MainMenu();
  void RecordData(bool record_data);
  void LoadFirstLidarImuData(bool load);
  void CompensateFirstLidarImuData(bool compensate);
  void LoadSecondLidarImuData(bool load);
  void CompensateSecondLidarImuData(bool compensate);
  void Save(bool save_dialog);
  void MouseControl();
  bool SaveExtrinsicParameter(std::string file_path, int index);
  bool SelfCalibration(int index_odom);

 private:
  Eigen::Vector2i framebuffer_size_;
  std::unique_ptr<guik::GLCanvas> main_canvas_;
  std::unique_ptr<guik::ProgressModal> progress_;
  std::unique_ptr<VersionModal> version_modal_;
  float downsample_resolution_;
  std::shared_ptr<KeyFrameParameter> key_frame_parameter_[2];
  std::shared_ptr<OdometryFrameSet> odometry_frame_set_[2];
  SelfLidarImuCalibrator self_clibrator_;
};

}  // namespace lidar_imu_calibrator
